/* Orbas:
 *     A open source CORBA Specification implementation from Huihoo.
 *
 * Copyright 2002-2003 Huihoo.org, Inc. All Right Reserved.
 *
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 *
 * For more information, visit:
 *
 * http://www.huihoo.org/orbas
 */

package org.huihoo.orbas.orb.giop;

/**
 * <p>Description: </p>
 * Client side GIOP implementation.
 * <p>Copyright (c) 2002,2003</p>
 * <p>Company: <a href="http://www.huihoo.org/">huihoo.org</a></p>
 * @author <a href="http://www.huihoo.org/~mep">mep(mep@huihoo.com)</a>
 * @see <a href="http://www.huihoo.org/orbas">http://www.huihoo.org/orbas</a>
 * @version 1.0
 */

import org.huihoo.orbas.orb.cdr.CDRInputStream;
import org.huihoo.orbas.orb.cdr.CDROutputStream;
import org.huihoo.orbas.orb.protocols.Transport;
//import org.omg.GIOP.*;
//import org.omg.IOP.*;

public class GiopClientWorker extends GiopWorker implements
		org.huihoo.orbas.orb.ClientWorker {

	protected Transport transport;
	org.huihoo.orbas.orb.protocols.TargetAddress target;

	int requestId;
	int version;

	// org.huihoo.orbas.orb.ORB orb;

	public GiopClientWorker(org.huihoo.orbas.orb.ORB orb, int version) {
		requestId = 0;
		this.orb = orb;
		this.version = version;
	}

	public int getRequestId() {
		return ++requestId;
	}

	public CDROutputStream createRequest(
			org.huihoo.orbas.orb.protocols.TargetAddress target,
			org.omg.GIOP.TargetAddress targetObject, String the_operation,
			boolean responseExpected) {

		this.target = target;
		// this.transport = null;

		CDROutputStream out = new CDROutputStream(orb);

		switch (version) {
		case 10:

			org.omg.GIOP.RequestHeader_1_0 request10 = new org.omg.GIOP.RequestHeader_1_0();

			request10.request_id = getRequestId();
			request10.response_expected = responseExpected;

			if (targetObject.discriminator() != org.omg.GIOP.KeyAddr.value) {
				// error?
			}

			request10.object_key = targetObject.object_key();
			request10.operation = the_operation;
			request10.requesting_principal = new byte[0];
			request10.service_context = new org.omg.IOP.ServiceContext[0];

			org.omg.GIOP.RequestHeader_1_0Helper.write(out, request10);

			break;

		case 11:

			org.omg.GIOP.RequestHeader_1_1 request11 = new org.omg.GIOP.RequestHeader_1_1();

			request11.request_id = getRequestId();
			request11.response_expected = responseExpected;

			if (targetObject.discriminator() != org.omg.GIOP.KeyAddr.value) {
				// error?
			}

			request11.object_key = targetObject.object_key();
			request11.operation = the_operation;
			request11.requesting_principal = new byte[0];
			request11.service_context = new org.omg.IOP.ServiceContext[0];
			request11.reserved = new byte[3];

			org.omg.GIOP.RequestHeader_1_1Helper.write(out, request11);

			break;

		case 12:

			org.omg.GIOP.RequestHeader_1_2 request12 = new org.omg.GIOP.RequestHeader_1_2();

			request12.request_id = getRequestId();
			request12.response_flags = 0x01;
			request12.reserved = new byte[3];

			request12.target = targetObject;
			request12.operation = the_operation;
			request12.service_context = new org.omg.IOP.ServiceContext[0];

			org.omg.GIOP.RequestHeader_1_2Helper.write(out, request12);

			break;

		default:
			// error
		}

		return out;
	}

	public CDRInputStream invoke(org.omg.CORBA.portable.OutputStream os)
			throws org.omg.CORBA.portable.ApplicationException,
			org.omg.CORBA.portable.RemarshalException {

		CDROutputStream headerOut = new CDROutputStream(orb);
		CDROutputStream bodyOut = (CDROutputStream) os;

		org.omg.GIOP.MessageHeader_1_1 messageHeader10 = new org.omg.GIOP.MessageHeader_1_1();

		messageHeader10.magic = new char[4];
		messageHeader10.magic[0] = 'G';
		messageHeader10.magic[1] = 'I';
		messageHeader10.magic[2] = 'O';
		messageHeader10.magic[3] = 'P';
		messageHeader10.GIOP_version = new org.omg.GIOP.Version();
		messageHeader10.GIOP_version.major = 1;
		messageHeader10.GIOP_version.minor = (byte) (version - 10);

		if (version == 10) {
			messageHeader10.flags = 0; // big endian
		} else {
			messageHeader10.flags = 0x0;
		}

		messageHeader10.message_type = org.omg.GIOP.MsgType_1_0._Request;
		messageHeader10.message_size = bodyOut.getLength() + 1;

		org.omg.GIOP.MessageHeader_1_1Helper.write(headerOut, messageHeader10);

		headerOut
				.write_octet_array(bodyOut.getBuffer(), 0, bodyOut.getLength());
		// write out GIOP header

		CDRInputStream ret = null;
		try {

			write(headerOut);

			ret = read();
			// check if it is a location forward
		} catch (java.io.IOException e) {
			e.printStackTrace();
		}

		headerOut = null;

		return ret;
	}

	public void invokeOneway(org.omg.CORBA.portable.OutputStream os) {

	}

	public CDROutputStream createLocateRequest(
			org.huihoo.orbas.orb.protocols.TargetAddress target) {
		CDROutputStream out = new CDROutputStream(orb);

		return out;
	}

	public Transport getTransport() {
		// initialize the channel
		if (transport == null) {
			// transport = target.initialChannel().setup();
			transport = orb.getTransportsPool().getTransport(target);
		}

		return transport;
	}

	public void setTransport(Transport t) {
		transport = t;
	}

}